#ifndef THINK_THINK_CONSOLE_COMMAND_OPTIMIZE_AUTOLOAD_H
#define THINK_THINK_CONSOLE_COMMAND_OPTIMIZE_AUTOLOAD_H

static char* think_console_command_optimize_autoload =
	"\n"
	"// +----------------------------------------------------------------------\n"
	"// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]\n"
	"// +----------------------------------------------------------------------\n"
	"// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.\n"
	"// +----------------------------------------------------------------------\n"
	"// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )\n"
	"// +----------------------------------------------------------------------\n"
	"// | Author: yunwuxin <448901948@qq.com>\n"
	"// +----------------------------------------------------------------------\n"
	"namespace think\\console\\command\\optimize;\n"
	"\n"
	"use think\\App;\n"
	"use think\\Config;\n"
	"use think\\console\\Command;\n"
	"use think\\console\\Input;\n"
	"use think\\console\\Output;\n"
	"\n"
	"class Autoload extends Command\n"
	"{\n"
	"\n"
	"    protected function configure()\n"
	"    {\n"
	"        $this->setName(\'optimize:autoload\')\n"
	"            ->setDescription(\'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.\');\n"
	"    }\n"
	"\n"
	"    protected function execute(Input $input, Output $output)\n"
	"    {\n"
	"\n"
	"        $classmapFile = <<<EOF\n"
	"<?php\n"
	"/**\n"
	" * 类库映射\n"
	" */\n"
	"\n"
	"return [\n"
	"\n"
	"EOF;\n"
	"\n"
	"        $namespacesToScan = [\n"
	"            App::$namespace . \'\\\\\' => realpath(rtrim(APP_PATH)),\n"
	"            \'think\\\\\'              => LIB_PATH . \'think\',\n"
	"            \'behavior\\\\\'           => LIB_PATH . \'behavior\',\n"
	"            \'traits\\\\\'             => LIB_PATH . \'traits\',\n"
	"            \'\'                     => realpath(rtrim(EXTEND_PATH)),\n"
	"        ];\n"
	"\n"
	"        $root_namespace = Config::get(\'root_namespace\');\n"
	"        foreach ($root_namespace as $namespace => $dir) {\n"
	"            $namespacesToScan[$namespace . \'\\\\\'] = realpath($dir);\n"
	"        }\n"
	"\n"
	"        krsort($namespacesToScan);\n"
	"        $classMap = [];\n"
	"        foreach ($namespacesToScan as $namespace => $dir) {\n"
	"\n"
	"            if (!is_dir($dir)) {\n"
	"                continue;\n"
	"            }\n"
	"\n"
	"            $namespaceFilter = $namespace === \'\' ? null : $namespace;\n"
	"            $classMap        = $this->addClassMapCode($dir, $namespaceFilter, $classMap);\n"
	"        }\n"
	"\n"
	"        ksort($classMap);\n"
	"        foreach ($classMap as $class => $code) {\n"
	"            $classmapFile .= \'    \' . var_export($class, true) . \' => \' . $code;\n"
	"        }\n"
	"        $classmapFile .= \"];\\n\";\n"
	"\n"
	"        if (!is_dir(RUNTIME_PATH)) {\n"
	"            @mkdir(RUNTIME_PATH, 0755, true);\n"
	"        }\n"
	"\n"
	"        file_put_contents(RUNTIME_PATH . \'classmap\' . EXT, $classmapFile);\n"
	"\n"
	"        $output->writeln(\'<info>Succeed!</info>\');\n"
	"    }\n"
	"\n"
	"    protected function addClassMapCode($dir, $namespace, $classMap)\n"
	"    {\n"
	"        foreach ($this->createMap($dir, $namespace) as $class => $path) {\n"
	"\n"
	"            $pathCode = $this->getPathCode($path) . \",\\n\";\n"
	"\n"
	"            if (!isset($classMap[$class])) {\n"
	"                $classMap[$class] = $pathCode;\n"
	"            } elseif ($classMap[$class] !== $pathCode && !preg_match(\'{/(test|fixture|example|stub)s?/}i\', strtr($classMap[$class] . \' \' . $path, \'\\\\\', \'/\'))) {\n"
	"                $this->output->writeln(\n"
	"                    \'<warning>Warning: Ambiguous class resolution, \"\' . $class . \'\"\' .\n"
	"                    \' was found in both \"\' . str_replace([\"\',\\n\"], [\n"
	"                        \'\',\n"
	"                    ], $classMap[$class]) . \'\" and \"\' . $path . \'\", the first will be used.</warning>\'\n"
	"                );\n"
	"            }\n"
	"        }\n"
	"        return $classMap;\n"
	"    }\n"
	"\n"
	"    protected function getPathCode($path)\n"
	"    {\n"
	"\n"
	"        $baseDir    = \'\';\n"
	"        $libPath    = $this->normalizePath(realpath(LIB_PATH));\n"
	"        $appPath    = $this->normalizePath(realpath(APP_PATH));\n"
	"        $extendPath = $this->normalizePath(realpath(EXTEND_PATH));\n"
	"        $rootPath   = $this->normalizePath(realpath(ROOT_PATH));\n"
	"        $path       = $this->normalizePath($path);\n"
	"\n"
	"        if ($libPath !== null && strpos($path, $libPath . \'/\') === 0) {\n"
	"            $path    = substr($path, strlen(LIB_PATH));\n"
	"            $baseDir = \'LIB_PATH\';\n"
	"        } elseif ($appPath !== null && strpos($path, $appPath . \'/\') === 0) {\n"
	"            $path    = substr($path, strlen($appPath) + 1);\n"
	"            $baseDir = \'APP_PATH\';\n"
	"        } elseif ($extendPath !== null && strpos($path, $extendPath . \'/\') === 0) {\n"
	"            $path    = substr($path, strlen($extendPath) + 1);\n"
	"            $baseDir = \'EXTEND_PATH\';\n"
	"        } elseif ($rootPath !== null && strpos($path, $rootPath . \'/\') === 0) {\n"
	"            $path    = substr($path, strlen($rootPath) + 1);\n"
	"            $baseDir = \'ROOT_PATH\';\n"
	"        }\n"
	"\n"
	"        if ($path !== false) {\n"
	"            $baseDir .= \" . \";\n"
	"        }\n"
	"\n"
	"        return $baseDir . (($path !== false) ? var_export($path, true) : \"\");\n"
	"    }\n"
	"\n"
	"    protected function normalizePath($path)\n"
	"    {\n"
	"        if ($path === false) {\n"
	"            return;\n"
	"        }\n"
	"        $parts    = [];\n"
	"        $path     = strtr($path, \'\\\\\', \'/\');\n"
	"        $prefix   = \'\';\n"
	"        $absolute = false;\n"
	"\n"
	"        if (preg_match(\'{^([0-9a-z]+:(?://(?:[a-z]:)?)?)}i\', $path, $match)) {\n"
	"            $prefix = $match[1];\n"
	"            $path   = substr($path, strlen($prefix));\n"
	"        }\n"
	"\n"
	"        if (substr($path, 0, 1) === \'/\') {\n"
	"            $absolute = true;\n"
	"            $path     = substr($path, 1);\n"
	"        }\n"
	"\n"
	"        $up = false;\n"
	"        foreach (explode(\'/\', $path) as $chunk) {\n"
	"            if (\'..\' === $chunk && ($absolute || $up)) {\n"
	"                array_pop($parts);\n"
	"                $up = !(empty($parts) || \'..\' === end($parts));\n"
	"            } elseif (\'.\' !== $chunk && \'\' !== $chunk) {\n"
	"                $parts[] = $chunk;\n"
	"                $up      = \'..\' !== $chunk;\n"
	"            }\n"
	"        }\n"
	"\n"
	"        return $prefix . ($absolute ? \'/\' : \'\') . implode(\'/\', $parts);\n"
	"    }\n"
	"\n"
	"    protected function createMap($path, $namespace = null)\n"
	"    {\n"
	"        if (is_string($path)) {\n"
	"            if (is_file($path)) {\n"
	"                $path = [new \\SplFileInfo($path)];\n"
	"            } elseif (is_dir($path)) {\n"
	"\n"
	"                $objects = new \\RecursiveIteratorIterator(new \\RecursiveDirectoryIterator($path), \\RecursiveIteratorIterator::SELF_FIRST);\n"
	"\n"
	"                $path = [];\n"
	"\n"
	"                /** @var \\SplFileInfo $object */\n"
	"                foreach ($objects as $object) {\n"
	"                    if ($object->isFile() && $object->getExtension() == \'php\') {\n"
	"                        $path[] = $object;\n"
	"                    }\n"
	"                }\n"
	"            } else {\n"
	"                throw new \\RuntimeException(\n"
	"                    \'Could not scan for classes inside \"\' . $path .\n"
	"                    \'\" which does not appear to be a file nor a folder\'\n"
	"                );\n"
	"            }\n"
	"        }\n"
	"\n"
	"        $map = [];\n"
	"\n"
	"        /** @var \\SplFileInfo $file */\n"
	"        foreach ($path as $file) {\n"
	"            $filePath = $file->getRealPath();\n"
	"\n"
	"            if (pathinfo($filePath, PATHINFO_EXTENSION) != \'php\') {\n"
	"                continue;\n"
	"            }\n"
	"\n"
	"            $classes = $this->findClasses($filePath);\n"
	"\n"
	"            foreach ($classes as $class) {\n"
	"                if (null !== $namespace && 0 !== strpos($class, $namespace)) {\n"
	"                    continue;\n"
	"                }\n"
	"\n"
	"                if (!isset($map[$class])) {\n"
	"                    $map[$class] = $filePath;\n"
	"                } elseif ($map[$class] !== $filePath && !preg_match(\'{/(test|fixture|example|stub)s?/}i\', strtr($map[$class] . \' \' . $filePath, \'\\\\\', \'/\'))) {\n"
	"                    $this->output->writeln(\n"
	"                        \'<warning>Warning: Ambiguous class resolution, \"\' . $class . \'\"\' .\n"
	"                        \' was found in both \"\' . $map[$class] . \'\" and \"\' . $filePath . \'\", the first will be used.</warning>\'\n"
	"                    );\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"\n"
	"        return $map;\n"
	"    }\n"
	"\n"
	"    protected function findClasses($path)\n"
	"    {\n"
	"        $extraTypes = \'|trait\';\n"
	"\n"
	"        $contents = @php_strip_whitespace($path);\n"
	"        if (!$contents) {\n"
	"            if (!file_exists($path)) {\n"
	"                $message = \'File at \"%s\" does not exist, check your classmap definitions\';\n"
	"            } elseif (!is_readable($path)) {\n"
	"                $message = \'File at \"%s\" is not readable, check its permissions\';\n"
	"            } elseif (\'\' === trim(file_get_contents($path))) {\n"
	"                return [];\n"
	"            } else {\n"
	"                $message = \'File at \"%s\" could not be parsed as PHP, it may be binary or corrupted\';\n"
	"            }\n"
	"            $error = error_get_last();\n"
	"            if (isset($error[\'message\'])) {\n"
	"                $message .= PHP_EOL . \'The following message may be helpful:\' . PHP_EOL . $error[\'message\'];\n"
	"            }\n"
	"            throw new \\RuntimeException(sprintf($message, $path));\n"
	"        }\n"
	"\n"
	"        if (!preg_match(\'{\\b(?:class|interface\' . $extraTypes . \')\\s}i\', $contents)) {\n"
	"            return [];\n"
	"        }\n"
	"\n"
	"        // strip heredocs/nowdocs\n"
	"        $contents = preg_replace(\'{<<<\\s*(\\\'?)(\\w+)\\\\1(?:\\r\\n|\\n|\\r)(?:.*?)(?:\\r\\n|\\n|\\r)\\\\2(?=\\r\\n|\\n|\\r|;)}s\', \'null\', $contents);\n"
	"        // strip strings\n"
	"        $contents = preg_replace(\'{\"[^\"\\\\\\\\]*+(\\\\\\\\.[^\"\\\\\\\\]*+)*+\"|\\\'[^\\\'\\\\\\\\]*+(\\\\\\\\.[^\\\'\\\\\\\\]*+)*+\\\'}s\', \'null\', $contents);\n"
	"        // strip leading non-php code if needed\n"
	"        if (substr($contents, 0, 2) !== \'<?\') {\n"
	"            $contents = preg_replace(\'{^.+?<\\?}s\', \'<?\', $contents, 1, $replacements);\n"
	"            if ($replacements === 0) {\n"
	"                return [];\n"
	"            }\n"
	"        }\n"
	"        // strip non-php blocks in the file\n"
	"        $contents = preg_replace(\'{\\?>.+<\\?}s\', \'?><?\', $contents);\n"
	"        // strip trailing non-php code if needed\n"
	"        $pos = strrpos($contents, \'?>\');\n"
	"        if (false !== $pos && false === strpos(substr($contents, $pos), \'<?\')) {\n"
	"            $contents = substr($contents, 0, $pos);\n"
	"        }\n"
	"\n"
	"        preg_match_all(\'{\n"
	"            (?:\n"
	"                 \\b(?<![\\$:>])(?P<type>class|interface\' . $extraTypes . \') \\s++ (?P<name>[a-zA-Z_\\x7f-\\xff:][a-zA-Z0-9_\\x7f-\\xff:\\-]*+)\n"
	"               | \\b(?<![\\$:>])(?P<ns>namespace) (?P<nsname>\\s++[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+(?:\\s*+\\\\\\\\\\s*+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*+)*+)? \\s*+ [\\{;]\n"
	"            )\n"
	"        }ix\', $contents, $matches);\n"
	"\n"
	"        $classes   = [];\n"
	"        $namespace = \'\';\n"
	"\n"
	"        for ($i = 0, $len = count($matches[\'type\']); $i < $len; $i++) {\n"
	"            if (!empty($matches[\'ns\'][$i])) {\n"
	"                $namespace = str_replace([\' \', \"\\t\", \"\\r\", \"\\n\"], \'\', $matches[\'nsname\'][$i]) . \'\\\\\';\n"
	"            } else {\n"
	"                $name = $matches[\'name\'][$i];\n"
	"                if ($name[0] === \':\') {\n"
	"                    $name = \'xhp\' . substr(str_replace([\'-\', \':\'], [\'_\', \'__\'], $name), 1);\n"
	"                } elseif ($matches[\'type\'][$i] === \'enum\') {\n"
	"                    $name = rtrim($name, \':\');\n"
	"                }\n"
	"                $classes[] = ltrim($namespace . $name, \'\\\\\');\n"
	"            }\n"
	"        }\n"
	"\n"
	"        return $classes;\n"
	"    }\n"
	"\n"
	"}\n"
	"\n"
;
#endif